define(function() {
    Function.prototype.top = function(argument) {
        this.__ziflag = 'top';
        return this;
    };
    Function.prototype.before = function(argument) {
        this.__ziflag = 'before';
        return this;
    };
    Function.prototype.after = function(argument) {
        this.__ziflag = 'after';
        return this;
    };

    Function.prototype.add_before = function(argument) {
        this.__add = 1;
        this.__ziflag = 'add_before';
        return this;
    };
    Function.prototype.add_after = function(argument) {
        this.__add = 1;
        this.__ziflag = 'add_after';
        return this;
    };

    Function.prototype.main = function(argument) {
        this.__ziflag = 'main';
        return this;
    };

    zisysid = 0;
    zi = {};
    zi.sys = {};
    zi.sys.reIns = [];
    zi.sys.list = {};
    zi.sys.getid = function() {
        return zisysid++;
    };
    zi.sys.request = [];
    zi.sys.rmem = function(rootname, addr) {
        this.__sys = {
            root: rootname,
            addr: addr
        };
        this.__sys.after = [];
        this.__sys.before = [];
        this.__sys.top = [];
    };
    zi.sys.rmem.prototype.go = function() {
        zi.sys.list[this.__sys.root + this.__sys.addr] = [this.__sys.root, this.__sys.addr, true]

    };
    zi.sys.rmem.prototype.clean_after = function() {
        if(zi.sys.list[this.__sys.root + this.__sys.addr]===undefined)
        zi.sys.list[this.__sys.root + this.__sys.addr] = [this.__sys.root, this.__sys.addr];
    };
    zi.sys.func = function(pakname, i, out) {
        this.__sys = {};
        this.__sys.pakname = pakname;
        this.__sys.i = i;
        this.__sys.out = out;
    };
    zi.sys.func.prototype.us = function() {
        var root = this.__sys.out.__sys.root;
        var us = zi.pak[this.__sys.pakname][this.__sys.i].__us;
        return zi.sys.get(root, us);
    };
      zi.sys.func.prototype.cut = function() {
        this.__sys.cut=true;
    };
    zi.sys.func.prototype.del = function() {
        this.__sys.del = 1;
    };
    zi.pak = function(name, data) {
        var id = zi.sys.getid();
        zi.sys.request[id] = {};
        var part = zi.sys.request[id];
        part.type = "pak";
        part.name = name;
        part.data = data;
        part.fin = true;
    };
    zi.ins = function(rootname, pakname) {
        var id = zi.sys.getid();
        zi.sys.request[id] = {};
        var part = zi.sys.request[id];
        part.type = "ins";
        part.rootname = rootname;
        part.pakname = pakname;
        part.fin = true;
    };
    zi.sys.get = function(rootname, addr) {
        if (zi.ins[rootname] === undefined) zi.ins[rootname] = {};
        if (zi.ins[rootname][addr] === undefined) zi.ins[rootname][addr] = new zi.sys.rmem(rootname, addr);
        return zi.ins[rootname][addr];

    };
    zi.sys.endfunc = function() {};
    zi.sys.endfunc.__ziflag = "end";
    zi.sys.core = function() {
        var request = zi.sys.request;
        var done = zi.sys.core.done;
        for (; request[done] !== undefined && request[done].fin; done++) {
            var info = request[done];

            switch (info.type) {

            case 'pak':
                if (zi.pak[info.name] === undefined) zi.pak[info.name] = [];
                else {
                    console.log("pak error:package " + info.name + " has already defined");
                    return;
                }
                var us;
                var tm;
                var data = info.data;
                var len = data.length;
                for (var i = 0; i < len; i++) {
                    switch (data[i].constructor) {
                    case Array:
                        zi.pak[info.name].push(zi.sys.endfunc);
                        us = data[i][0];
                        break;
                    case String:
                        tm = data[i];
                        break;
                    case Function:
                        var func = data[i];
                        if (us === undefined) {
                            console.log("pak error: no us before a function: " + info.name + " at " + (i + 1));
                            return;
                        } else if (func.__ziflag === undefined) {
                            console.log("pak error: a function did not defined its type: " + info.name + " at " + (i + 1));
                            return;
                        } else if (tm === undefined && func.__add === 1) {
                            console.log("pak error: no tm before a adding function: " + info.name + " at " + (i + 1));
                            return;
                        }
                        func.__us = us;
                        if (func.__add === 1) func.__tm = tm;
                        zi.pak[info.name].push(func);
                    }

                };
                var reIns = zi.sys.reIns[info.name];
                if (reIns === undefined) {

                    break;
                };
                var len = reIns.length;
                for (var i = 0; i < len; i++) {
                    zi.ins(reIns[i], info.name);

                };
                delete zi.sys.reIns[info.name];
                break;

            case 'ins':
                if (zi.pak[info.pakname] === undefined) {
                    require([info.pakname],
                    function(pak) {
                        zi.pak(pak.name, pak.data);

                    });
                    if (zi.sys.reIns[info.pakname] === undefined) {
                        zi.sys.reIns[info.pakname] = [];
                    };
                    zi.sys.reIns[info.pakname].push(info.rootname);
                    break;

                };
                var data = zi.pak[info.pakname];
                var len = data.length;
                var us;
                var tempmain;
                for (var i = 0; i < len; i++) {
                    var func = data[i];
                    switch (func.__ziflag) {
                    case 'main':
                        tempmain = zi.sys.get(info.rootname, func.__us);
                        if (tempmain.__main !== undefined) {
                            console.log("ins error: " + info.rootname + " " + func.__us + " hava already defined main" + "but pak " + info.pakname + " try to redeine");

                            return;
                        };
                        us = func.__us;
                        tempmain.__main = new zi.sys.func(info.pakname, i, tempmain);
                        break;

                    case 'after':
                        zi.sys.get(info.rootname, func.__us).__sys.after.push(new zi.sys.func(info.pakname, i, tempmain));
                        zi.sys.get(info.rootname, func.__us).clean_after();
                        break;
                    case 'top':
                        zi.sys.get(info.rootname, func.__us).__sys.top.push(new zi.sys.func(info.pakname, i, tempmain));
                        break;
                    case 'before':
                        zi.sys.get(info.rootname, func.__us).__sys.before.push(new zi.sys.func(info.pakname, i, tempmain));
                        break;
                    case 'add_after':
                        zi.sys.get(info.rootname, func.__tm).__sys.after.push(new zi.sys.func(info.pakname, i, tempmain));
                        zi.sys.get(info.rootname, func.__tm).clean_after();
                        break;
                    case 'add_before':
                        zi.sys.get(info.rootname, func.__tm).__sys.before.push(new zi.sys.func(info.pakname, i, tempmain));
                        break;
                    case 'end':
                        if (us!==undefined)
                        zi.sys.get(info.rootname, us).go();
                        break;
                    default:
                        console.log("ins error:unknow error");

                    }
                }
                break;
            default:
                console.log('core error:unknow error');

            };
            delete zi.sys.request[done];
        };
        zi.sys.core.done = done;
        var list = zi.sys.list;
        var iscut = false;
        var i;
        for (i in list) {
            var root = list[i][0];
            var addr = list[i][1];
            var flag=list[i][2]
            delete list[i];
            var rmem = zi.ins[root][addr];
            zi.ins[root][addr].__sys.run = 1;
            if (flag) {
                iscut=false;
                for (var i2 = 0; i2 < rmem.__sys.top.length; i2++) {
                    var data = rmem.__sys.top[i2];
                    zi.pak[data.__sys.pakname][data.__sys.i].call(zi.ins[root][addr].__sys.top[i2]);
                    if (zi.ins[root][addr].__sys.top[i2].__sys.cut) {
                        iscut = true;
                        zi.ins[root][addr].__sys.top[i2].__sys.cut=false;
                        break;
                    };
                    if (zi.ins[root][addr].__sys.top[i2].__sys.del === 1) {
                        zi.ins[root][addr].__sys.top.splice(i2,1);
                        i2--;
                    };
                };
                if (iscut) {
                    continue;
                };
                for (var i2 = 0; i2 < rmem.__sys.before.length; i2++) {
                    var data = rmem.__sys.before[i2];
                    zi.pak[data.__sys.pakname][data.__sys.i].call(zi.ins[root][addr].__sys.before[i2]);
                    if (zi.ins[root][addr].__sys.before[i2].__sys.del === 1) {
                        zi.ins[root][addr].__sys.before.splice(i2,1);
                        i2--;
                    };
                };
                var data = rmem.__main;
                zi.ins[root][addr].__return=zi.pak[data.__sys.pakname][data.__sys.i].call(zi.ins[root][addr].__main);
                for (var i2 = 0; i2 < rmem.__sys.after.length; i2++) {
                    var data = rmem.__sys.after[i2];
                    zi.pak[data.__sys.pakname][data.__sys.i].call(zi.ins[root][addr].__sys.after[i2],zi.ins[root][addr].__return);
                    zi.ins[root][addr].__sys.after[i2].__sys.run = true;
                    if (zi.ins[root][addr].__sys.after[i2].__sys.del === 1) {
                        zi.ins[root][addr].__sys.after.splice(i2,1);
                        i2--;
                    };
                };

            } else {

                for (var i2 = 0; i2 < rmem.__sys.after.length; i2++) {
                    if (zi.ins[root][addr].__sys.after[i2].__sys.run === false) {
                        var data = rmem.__sys.after[i2];
                        zi.pak[data.__sys.pakname][data.__sys.i].call(zi.ins[root][addr].__sys.after[i2],zi.ins[root][addr].__return);
                        zi.ins[root][addr].__sys.after[i2].__sys.run = true;
                        if (zi.ins[root][addr].__sys.after[i2].__sys.del === 1) {
                            zi.ins[root][addr].__sys.after.splice(i2,1);
                            i2--;
                        };
                    };
                };

            };

            
        };

        setTimeout(zi.sys.core, 100);

    };
    zi.sys.core.done = 0;

    setTimeout(zi.sys.core, 200);
});